package com.easyexcel.demo.write.handler;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

@Slf4j
public class MergeCellWriteHandler implements CellWriteHandler {
    /**
     * 在 Cell 定入后处理
     *
     * @param writeSheetHolder
     * @param writeTableHolder
     * @param cellDataList
     * @param cell 当前 Cell
     * @param head
     * @param relativeRowIndex 表格内容行索引，从除表头的第一行开始，索引为0
     * @param isHead 是否是表头，true表头，false非表头
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        //判断当前为表头，不执行操作
        if (isHead) {
            log.info("\r\n当前为表头, 不执行操作");
            return;
        }

        /*
         * 判断当前 Cell 所在列索引不是0，1，5，不执行操作
         *  说明：不添加当前代码判断，整个表都会进行跨行合并
         *
         * 添加列索引为2的，处理跨列合并
         */
        if (cell.getColumnIndex() != 0 && cell.getColumnIndex() != 1 && cell.getColumnIndex() != 2 && cell.getColumnIndex() != 5) {
            log.info("\r\n当前不是 [0, 1, 2, 5] 其中一列, 不执行操作");
            return;
        }

        //当前 Sheet
        Sheet sheet = cell.getSheet();
        //当前 Cell 所在行索引
        int rowIndexCurr = cell.getRowIndex();
        //当前 Cell 所在行的上一行索引
        int rowIndexPrev = rowIndexCurr - 1;
        //当前 Cell 所在行的 Row 对象
        Row rowCurr = cell.getRow();
        //当前 Cell 所在行的上一行 Row 对象
        Row rowPrev = sheet.getRow(rowIndexPrev);
        //当前单元格的上一行同列单元格
        Cell cellPrev = rowPrev.getCell(cell.getColumnIndex());

        if (cell.getColumnIndex() == 0 || cell.getColumnIndex() == 1 || cell.getColumnIndex() == 5) {
            log.info("\r\n当前处理第 [0, 1, 5] 列单元格跨行合并");

            //当前单元格的值
            Object cellValueCurr = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
            //上面单元格的值
            Object cellValuePrev = cellPrev.getCellType() == CellType.STRING ? cellPrev.getStringCellValue() : cellPrev.getNumericCellValue();
            log.info("\r\n当前单元格值: " + cellValueCurr + ", 上面单元格的值: " + cellValuePrev + ", 两个单元格值不相等, 不执行操作");

            //判断当前单元格与上面单元格是否相等，不相等不执行操作
            if (!cellValueCurr.equals(cellValuePrev)) {
                log.info("\r\n两个单元格值不相等, 不执行操作");
                return;
            }

            log.info("\r\n两个单元格值相等, 开始进行合并操作");

            /*
             *需要注意，合并时，以第一列（地市）为准
             * 当第一列上下两个单元格不一样时，说明不是一个地市数据，其他列单元格值相等也不能进行合并
             * 由于可以通过数据知道第一列为字符型数据，可以直接获取
             */
            if (!rowPrev.getCell(0).getStringCellValue().equals(rowCurr.getCell(0).getStringCellValue())) {
                log.info("\r\n开始 " + rowCurr.getCell(0).getStringCellValue() + "地市数据合并操作");
                return;
            }

            //从 Sheet 中，获取所有合并区域
            List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
            //是否合并过
            boolean merged = false;
            //遍历合并区域集合
            for (int i = 0; i < mergedRegions.size(); i++) {
                CellRangeAddress cellAddresses = mergedRegions.get(i);
                //判断 cellAddress 的范围是否是从 rowIndexPrev 到 cell.getColumnIndex()
                if (cellAddresses.isInRange(rowIndexPrev, cell.getColumnIndex())) {
                    //从集合中移除
                    sheet.removeMergedRegion(i);
                    //设置范围最后一行，为当前行
                    cellAddresses.setLastRow(rowIndexCurr);
                    //重新添加到 Sheet 中
                    sheet.addMergedRegion(cellAddresses);
                    //已完成合并
                    merged = true;
                    break;
                }
            }

            //merged=false，表示当前单元格为第一次合并
            if (!merged) {
                CellRangeAddress cellAddresses = new CellRangeAddress(rowIndexPrev, rowIndexCurr, cell.getColumnIndex(), cell.getColumnIndex());
                sheet.addMergedRegion(cellAddresses);
            }
        } else if (cell.getColumnIndex() == 2) {
            log.info("\r\n当前处理第 [2] 列单元格跨列合并");

            //当前行的第二列，索引为1
            Cell cell1 = rowCurr.getCell(1);
            //当前行的第三列，索引为2
            Cell cell2 = rowCurr.getCell(2);

            //判断只要两个单元格值相等，就可以直接进行合并
            if (cell1 != null && cell2 != null && cell1.getStringCellValue().equals(cell2.getStringCellValue())) {
                //创建一个当前行到当前行，索引为1的列到索引为2的列的合并，并添加到 Sheet 中
                sheet.addMergedRegion(new CellRangeAddress(rowIndexCurr, rowIndexCurr, cell1.getColumnIndex(), cell2.getColumnIndex()));
            }
        } else {
            return;
        }

        log.info("\r\n合并单元格完成");
    }
}
